package ClientCommands;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

import org.json.simple.JSONObject;

import ServiceLayer.ServiceFacade;

import Annotations.AttributeNameAnnotation;
import Annotations.IsClientCommand;
import Commands.ClientCommandBase;
import Commands.ExecuteMethod;
import DomainLayer.MPAARatingStatus;
import DomainLayer.MovieEntity;
import DomainLayer.ProfitValueObject;
import Helpers.ApplicationLogger;

@IsClientCommand
public class AddMovie extends ClientCommandBase<Boolean> {
	private String movieDescription;
	private double ratingIMDB;
	private MPAARatingStatus ratingMPAA;
	private int rating;
	private String name;

	private double profitInRussia;
	private double profitInUSA;
	private double profitInEurope;
	private double profitInOtherCountries;
	private double profitFromTV;
	private double profitFromDVD;

	private HashSet<String> genre = new HashSet<String>();
	private String cover;
	private ProfitValueObject profit;
	private ArrayList<String> actors = new ArrayList<String>();
	private Integer id;

	private String genresString;
	private String actorsString;

	public String getGenresString() {
		return genresString;
	}

	public void setGenresString(String genresString) {
		this.genresString = genresString;
	}

	public String getActorsString() {
		return actorsString;
	}

	public void setActorsString(String actorsString) {
		this.actorsString = actorsString;
	}

	public ArrayList<String> getActors() {
		return actors;
	}

	public void setActors(ArrayList<String> actors) {
		this.actors = actors;
	}

	public double getProfitInRussia() {
		return profitInRussia;
	}

	public void setProfitInRussia(double profitInRussia) {
		this.profitInRussia = profitInRussia;
	}

	public double getProfitInUSA() {
		return profitInUSA;
	}

	public void setProfitInUSA(double profitInUSA) {
		this.profitInUSA = profitInUSA;
	}

	public double getProfitInEurope() {
		return profitInEurope;
	}

	public void setProfitInEurope(double profitInEurope) {
		this.profitInEurope = profitInEurope;
	}

	public double getProfitInOtherCountries() {
		return profitInOtherCountries;
	}

	public void setProfitInOtherCountries(double profitInOtherCountries) {
		this.profitInOtherCountries = profitInOtherCountries;
	}

	public double getProfitFromTV() {
		return profitFromTV;
	}

	public void setProfitFromTV(double profitFromTV) {
		this.profitFromTV = profitFromTV;
	}

	public double getProfitFromDVD() {
		return profitFromDVD;
	}

	public void setProfitFromDVD(double profitFromDVD) {
		this.profitFromDVD = profitFromDVD;
	}

	public String getCover() {
		return cover;
	}

	public void setCover(String cover) {
		this.cover = cover;
	}

	public MPAARatingStatus getRatingMPAA() {
		return ratingMPAA;
	}

	public void setRatingMPAA(MPAARatingStatus ratingMPAA) {
		this.ratingMPAA = ratingMPAA;
	}

	public void addGenre(String genre) {
		this.genre.add(genre);
	}

	public void removeGenre(String genre) {
		this.genre.remove(genre);
	}

	public HashSet<String> getGenre() {
		return genre;
	}

	public void setGenre(HashSet<String> genre) {
		this.genre = genre;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getMovieDescription() {
		return movieDescription;
	}

	public void setMovieDescription(String movieDescription) {
		this.movieDescription = movieDescription;
	}

	public double getRatingIMDB() {
		return ratingIMDB;
	}

	public void setRatingIMDB(double ratingIMDB) {
		this.ratingIMDB = ratingIMDB;
	}

	public int getRating() {
		return rating;
	}

	public void setRating(int rating) {
		this.rating = rating;
	}

	public ProfitValueObject getProfit() {
		return profit;
	}

	public void setProfit(ProfitValueObject profit) {
		this.profit = profit;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public AddMovie() {
		setCommandName("AddMovie");
		setCommandDescription("Adds new movie");
		setExecuteMethod(ExecuteMethod.ServerOnly);
	}

	@Override
	protected void ExecuteInternal() throws IOException {
		Boolean status = false;
		try {
			ServiceLayer.ServiceFacade sf = new ServiceFacade();
			ApplicationLogger.getInstance().LOG
					.info("   Execute internal (AddMovie)");
			MovieEntity movie = new MovieEntity();
			movie.setCover(getCover());
			movie.setMovieDescription(getMovieDescription());
			movie.setName(getName());
			movie.setRating(getRating());
			movie.setRatingIMDB(getRatingIMDB());
			movie.setRatingMPAA(getRatingMPAA());
			movie.setProfit(getProfit());

			ApplicationLogger.getInstance().LOG
					.info("   Execute internal (prepared to filling collections); actorsString: "
							+ actorsString + " genresString: " + genresString);
			fillCollection(actors, actorsString, ",");
			ApplicationLogger.getInstance().LOG
					.info("   Execute internal (actors filled)");
			fillCollection(genre, genresString, ",");
			ApplicationLogger.getInstance().LOG
					.info("   Execute internal (genres filled)");
			movie.setActors(getActors());
			movie.setGenre(getGenre());

			status = sf.AddMovie(movie);
		} catch (Exception e) {
			ApplicationLogger.getInstance().LOG.error(
					"Exception in Execute internal of AddMovie comand", e);
		} catch (Throwable e) {
			ApplicationLogger.getInstance().LOG.error(
					"Exception in Execute internal of AddMovie comand", e);
		}
		setResult(status);
		ApplicationLogger.getInstance().LOG.info("   ExecuteD internal");
	}

	private void fillCollection(Collection collection, String resource,
			String delims) {
		String[] tokens = actorsString.split(delims);
		badInput1: for (String s : tokens) {
			while (s.startsWith(" ")) {
				if (s.length() > 1)
					s = s.substring(1, s.length());
				else
					break badInput1;
			}
			collection.add(s);
		}
	}

	@Override
	public void FillFromJSON(JSONObject jObj) {
		super.FillFromJSON(jObj);
		try {
			ApplicationLogger.getInstance().LOG
					.info("   Filling from JSON a Movie");

			// setActors((ArrayList<String>) (jObj.get("Actors")));
			setCover((String) jObj.get("Cover"));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (Cover)");
			// setGenre((HashSet<String>) (jObj.get("Genre")));
			// setId((Integer) (jObj.get("Id")));
			setGenresString(String.valueOf(jObj.get("GenresString")));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (GenresString)");
			setActorsString(String.valueOf(jObj.get("ActorsString")));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (Actors string)");
			setMovieDescription(String.valueOf(jObj.get("MovieDescription")));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (Description)");
			setName((String) (jObj.get("Name")));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (Name)");
			setProfit(new ProfitValueObject(
					new ProfitValueObject(),
					0,
					Double.parseDouble(String.valueOf(jObj
							.get("ProfitInRussia"))),
					Double.parseDouble(String.valueOf(jObj.get("ProfitInUSA"))),
					Double.parseDouble(String.valueOf(jObj
							.get("ProfitInEurope"))),
					Double.parseDouble(String.valueOf(jObj
							.get("ProfitInOtherCountries"))),
					Double.parseDouble(String.valueOf(jObj.get("ProfitFromTV"))),
					Double.parseDouble(String.valueOf(jObj.get("ProfitFromDVD")))));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (Profit) in Russia:"
							+ String.valueOf(jObj.get("ProfitInRussia")));
			ApplicationLogger.getInstance().LOG.info("--------"
					+ jObj.get("Rating"));
			setRating(Integer.parseInt((String) (jObj.get("Rating"))));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (Rating)");
			setRatingIMDB(Double.parseDouble((String) jObj.get("RatingIMDB")));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (Rating IMDB)");
			ApplicationLogger.getInstance().LOG
					.info("   +++++++++++++++++++++++++"
							+ jObj.get("RatingMPAA"));
			setRatingMPAA(MPAARatingStatus.valueOf(String.valueOf(jObj
					.get("RatingMPAA"))));
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie (Rating MPAA)");
			ApplicationLogger.getInstance().LOG
					.info("   Filled from JSON a Movie");
		} catch (Throwable t) {
			ApplicationLogger.getInstance().LOG.error(
					"Error while filling from JSON a Movie!", t);
		}
	}

	@Override
	public String toJSONString() {
		StringBuffer sb = new StringBuffer();
		ApplicationLogger.getInstance().LOG
				.info("+++++++++++++JSON generation started!: " + sb);
		sb.append("{");
		try {
			sb.append("\"" + JSONObject.escape("CommandName") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getCommandName()) + "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("CommandDescription") + "\"");
			sb.append(":");
			sb.append("\"" + getCommandDescription() + "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("ExecuteMethod") + "\"");
			sb.append(":");
			sb.append("\"" + getExecuteMethod() + "\"");
			// sb.append(",");
			// ApplicationLogger.getInstance().LOG.info("generated JSON: " +
			// sb);
			// // sb.append("\"" + JSONObject.escape("Id") + "\"");
			// // sb.append(":");
			// // sb.append("\"" + JSONObject.escape(getId().toString()) +
			// "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("MovieDescription") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getMovieDescription()) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("GenresString") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getMovieDescription()) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("ActorsString") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getMovieDescription()) + "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("RatingIMDB") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(String.valueOf(getRatingIMDB()))
					+ "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("RatingMPAA") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(String.valueOf(getRatingMPAA()))
					+ "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("Rating") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(String.valueOf(getRating()))
					+ "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("Name") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getName()) + "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("ProfitInRussia") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfitInRussia()))
					+ "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("ProfitInUSA") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfitInUSA()))
					+ "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("ProfitInEurope") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfitInEurope()))
					+ "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("ProfitInOtherCountries") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String
							.valueOf(getProfitInOtherCountries())) + "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("ProfitFromTV") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfitFromTV()))
					+ "\"");
			sb.append(",");
			ApplicationLogger.getInstance().LOG.info("generated JSON: " + sb);
			sb.append("\"" + JSONObject.escape("ProfitFromDVD") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfitFromDVD()))
					+ "\"");
			// sb.append(",");
			// ApplicationLogger.getInstance().LOG.info("generated JSON: " +
			// sb);
			// // sb.append("\"" + JSONObject.escape("Genre") + "\"");
			// // sb.append(":");
			// // sb.append("\"" + JSONObject.escape(getGenre().toString()) +
			// "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("Cover") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getCover()) + "\"");
			// // sb.append(",");
			// // sb.append("\"" + JSONObject.escape("Profit") + "\"");
			// // sb.append(":");
			// // sb.append("\"" + JSONObject.escape(getProfit().toString()) +
			// "\"");
			// // sb.append(",");
			// // sb.append("\"" + JSONObject.escape("Actors") + "\"");
			// // sb.append(":");
			// // sb.append("\"" + JSONObject.escape(getActors().toString()) +
			// "\"");
			ApplicationLogger.getInstance().LOG
					.info("--------------------(end) generated JSON: " + sb);
		} catch (Exception e) {
			ApplicationLogger.getInstance().LOG
					.error("toJSONString failed!", e);
		} finally {
			sb.append("}");
			return sb.toString();
		}
	}
}